/*
 * @Author: 吴世扬 18368095041@163.com
 * @Date: 2024-10-10 16:30:46
 * @LastEditors: 吴世扬 18368095041@163.com
 * @LastEditTime: 2024-10-16 09:49:30
 * @FilePath: /react18-vite-admin/src/store/modules/enum.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */

import { create } from 'zustand';

import { treeToArray } from '@/utils/array';
import type {
    EnumStore,
    EnumItem,
    EnumType,
    RecordType
} from '@/typings/store/enum';
import { readAllRoles } from '@/api/role';
import { readDeptTree } from '@/api/department';
import { readMenuTree } from '@/api/menu';

const labelValueFormat = <T extends object>(
    target: T[],
    label: keyof T,
    value: keyof T
) => {
    return target.map((item) => {
        const returnVal: EnumItem<T> = {
            label: item[label] as string,
            value: item[value] as string | number,
            origin: item,
            children: []
        };
        if (Reflect.has(item, 'children')) {
            const children = Reflect.get(item, 'children');
            if (Array.isArray(children)) {
                returnVal.children = labelValueFormat(children, label, value);
            }
        }
        return returnVal;
    });
};

export const useEnumStore = create<EnumStore>((set, get) => {
    return {
        roleType: [],
        validType: [
            {
                label: '有效',
                value: 1
            },
            {
                label: '无效',
                value: 0
            }
        ],
        deptTreeItems: [],
        menuTreeItems: [],
        isExist(enumType) {
            return get()[enumType].length > 0;
        },
        getLabelByValue(enumType: EnumType, value: string | number) {
            const treeOrList = get()[enumType];
            const arr = treeToArray(treeOrList as EnumItem<unknown>[]);
            const item = arr.find((item) => item.value === value);
            if (item) {
                return item.label;
            }
            return '';
        },
        getItemByValue<
            T extends EnumType,
            O = RecordType[T] extends Array<infer U> ? U : never
        >(enumType: T, value: string | number) {
            const treeOrList = get()[enumType];
            const data = treeToArray(treeOrList as EnumItem<unknown>[]);
            const item = data.find((item) => item.value === value);
            if (item) {
                return item as unknown as O & { parent?: O };
            }
            return undefined;
        },
        handleUpdate(updateTypes: EnumType[]) {
            const pList: Array<Promise<Partial<RecordType>>> = [];
            updateTypes.forEach((key) => {
                switch (key) {
                    case 'roleType':
                        get().isExist(key)
                            ? undefined
                            : pList.push(
                                  new Promise((resolve) => {
                                      readAllRoles().then((res) => {
                                          resolve({
                                              roleType: labelValueFormat(
                                                  res.data,
                                                  'name',
                                                  'id'
                                              )
                                          });
                                      });
                                  })
                              );
                        break;
                    case 'deptTreeItems':
                        get().isExist(key)
                            ? undefined
                            : pList.push(
                                  new Promise((resolve) => {
                                      readDeptTree().then((res) => {
                                          resolve({
                                              deptTreeItems: labelValueFormat(
                                                  res.data,
                                                  'name',
                                                  'id'
                                              )
                                          });
                                      });
                                  })
                              );
                        break;
                    case 'menuTreeItems':
                        get().isExist(key)
                            ? undefined
                            : pList.push(
                                  new Promise((resolve) => {
                                    readMenuTree().then((res) => {
                                          resolve({
                                              menuTreeItems: labelValueFormat(
                                                  res.data,
                                                  'name',
                                                  'id'
                                              )
                                          });
                                      });
                                  })
                              );
                        break;
                    default:
                        break;
                }
            });
            Promise.all(pList).then((resArr) => {
                let data = {};
                resArr.forEach((res) => {
                    data = {
                        ...data,
                        ...res
                    };
                });
                set(data);
            });
        }
    };
});
